#!/usr/bin/perl

#%# family=auto
#%# capabilities=autoconf

use Munin::Plugin;

$pos   = undef;
$connected = 0;
$connectedimap = 0;
$connectedpop3 = 0;
$connectedproxyimap = 0;
$connectedproxypop3 = 0;
$connections = 0;
$connectionsimap = 0;
$connectionspop3 = 0;
$connectionsproxyimap = 0;
$connectionsproxypop3 = 0;
$login = 0;
$pop3login = 0;
$imaplogin = 0;
$tls = 0;
$starttls = 0;
$ssl = 0;
$aborted = 0;

($dirname = $0) =~ s/[^\/]+$//;

$logfile = $ENV{'LOGFILE'} || '/var/log/dovecot/info';

# Use an overrided $PATH for all external programs if needed
$DOVEADM = "/opt/local/bin/doveadm";

if ( $ARGV[0] and $ARGV[0] eq "autoconf" ) {

  if (! -x $DOVEADM) {
    print "no (no doveadm)\n";
    exit(1);
  }

  if (! -f $logfile) {
    print "no (logfile $logfile does not exist)\n";
    exit(1);
  }

  if (-r "$logfile") {
    print "yes\n";
    exit 0;
  } else {
    print "no (logfile not readable)\n";
  }
  exit 1;
}

if (-f "$logfile.0") {
  $rotlogfile = $logfile . ".0";
} elsif (-f "$logfile.1") {
  $rotlogfile = $logfile . ".1";
} elsif (-f "$logfile.01") {
  $rotlogfile = $logfile . ".01";
} else {
  $rotlogfile = $logfile . ".0";
}

if ( $ARGV[0] and $ARGV[0] eq "config" ) {
  print "multigraph dovecot_connections\n";
  print "graph_title Dovecot connections\n";
  print "graph_args --base 1000 -l 0 --no-gridfit --slope-mode\n";
  print "graph_vlabel connections\n";
  print "graph_category dovecot\n";
  print "connections.label Connections open\n";
  print "connections.type GAUGE\n";
  print "connections.draw LINE1\n";
  print "connections.min 0\n";
  print "connectionsimap.label IMAP\n";
  print "connectionsimap.type GAUGE\n";
  print "connectionsimap.draw AREA\n";
  print "connectionsimap.min 0\n";
  print "connectionspop3.label POP3\n";
  print "connectionspop3.type GAUGE\n";
  print "connectionspop3.draw STACK\n";
  print "connectionspop3.min 0\n";
  print "connectionsproxyimap.label PROXY-IMAP\n";
  print "connectionsproxyimap.type GAUGE\n";
  print "connectionsproxyimap.draw AREA\n";
  print "connectionsproxyimap.min 0\n";
  print "connectionsproxypop3.label PROXY-POP3\n";
  print "connectionsproxypop3.type GAUGE\n";
  print "connectionsproxypop3.draw STACK\n";
  print "connectionsproxypop3.min 0\n";

  print "multigraph dovecot_connected\n";
  print "graph_title Dovecot connected users\n";
  print "graph_args --base 1000 -l 0 --no-gridfit --slope-mode\n";
  print "graph_vlabel connections\n";
  print "graph_category dovecot\n";
  print "connected.label Connected users\n";
  print "connected.type GAUGE\n";
  print "connected.draw LINE1\n";
  print "connected.min 0\n";
  print "connectedimap.label IMAP\n";
  print "connectedimap.type GAUGE\n";
  print "connectedimap.draw AREA\n";
  print "connectedimap.min 0\n";
  print "connectedpop3.label POP3\n";
  print "connectedpop3.type GAUGE\n";
  print "connectedpop3.draw STACK\n";
  print "connectedpop3.min 0\n";
  print "connectedproxyimap.label PROXY-IMAP\n";
  print "connectedproxyimap.type GAUGE\n";
  print "connectedproxyimap.draw AREA\n";
  print "connectedproxyimap.min 0\n";
  print "connectedproxypop3.label PROXY-POP3\n";
  print "connectedproxypop3.type GAUGE\n";
  print "connectedproxypop3.draw STACK\n";
  print "connectedproxypop3.min 0\n";

  print "multigraph dovecot_logins\n";
  print "graph_title Dovecot logins\n";
  print "graph_args --base 1000 -l 0 --no-gridfit --slope-mode\n";
  print "graph_vlabel logins/5 minute\n";
  print "graph_category dovecot\n";
  print "login.label Logins\n";
  print "login.type GAUGE\n";
  print "login.draw LINE1\n";
  print "login.min 0\n";
  print "imaplogin.label IMAP logins\n";
  print "imaplogin.type GAUGE\n";
  print "imaplogin.draw LINE1\n";
  print "imaplogin.min 0\n";
  print "pop3login.label POP3 logins\n";
  print "pop3login.type GAUGE\n";
  print "pop3login.draw LINE1\n";
  print "pop3login.min 0\n";
  print "tls.label TLS\n";
  print "tls.type GAUGE\n";
  print "tls.draw LINE1\n";
  print "tls.min 0\n";
  print "starttls.label StartTLS\n";
  print "starttls.type GAUGE\n";
  print "starttls.draw LINE1\n";
  print "starttls.min 0\n";
  print "ssl.label SSL\n";
  print "ssl.type GAUGE\n";
  print "ssl.draw LINE1\n";
  print "ssl.min 0\n";
  print "aborted.label Aborted logins\n";
  print "aborted.type GAUGE\n";
  print "aborted.draw LINE1\n";
  print "aborted.min 0\n";
  exit 0;
}

if (! -f $logfile and ! -f $rotlogfile) {
  print "multigraph dovecot_connections\n";
  print "connections.value U";
  print "connectionsimap.value U";
  print "connectionspop3.value U";
  print "connectionsproxyimap.value U";
  print "connectionsproxypop3.value U";
  print "multigraph dovecot_connected\n";
  print "connected.value U\n";
  print "connectedimap.value U\n";
  print "connectedpop3.value U\n";
  print "connectedproxyimap.value U\n";
  print "connectedproxypop3.value U\n";
  print "multigraph dovecot_logins\n";
  print "login.value U\n";
  print "pop3login.value U\n";
  print "imaplogin.value U\n";
  print "tls.value U\n";
  print "starttls.value U\n";
  print "ssl.value U\n";
  print "aborted.value U\n";

  exit 0;
}

# dit kan beter maar twee calls zijn toch nodig als we niet zelf aggegreren
#  suggestie: doveadm who -1  | awk '{print $1" "$2" "$4}' | sort | uniq -c
$connectedimap   = `$DOVEADM -f flow who    | grep imap | wc -l`;
$connectedpop3   = `$DOVEADM -f flow who    | grep pop3 | wc -l`;
$connectionsimap = `$DOVEADM -f flow who -1 | grep imap | wc -l`;
$connectionspop3 = `$DOVEADM -f flow who -1 | grep pop3 | wc -l`;

$connectedproxyimap   = `$DOVEADM -f flow proxy list | sort | uniq | grep imap | wc -l`;
$connectedproxypop3   = `$DOVEADM -f flow proxy list | sort | uniq | grep pop3 | wc -l`;
$connectionsproxyimap = `$DOVEADM -f flow proxy list | grep imap | wc -l`;
$connectionsproxypop3 = `$DOVEADM -f flow proxy list | grep pop3 | wc -l`;

#trim
$connectedimap   =~ s/\s+$//;
$connectedpop3   =~ s/\s+$//;
$connectionsimap =~ s/\s+$//;
$connectionspop3 =~ s/\s+$//;

$connectedproxyimap   =~ s/\s+$//;
$connectedproxypop3   =~ s/\s+$//;
$connectionsproxyimap =~ s/\s+$//;
$connectionsproxypop3 =~ s/\s+$//;

$connected   = $connectedimap   + $connectedpop3 + $connectedproxyimap + $connectedproxypop3;
$connections = $connectionsimap + $connectionspop3 + $connectionsproxyimap + $connectionsproxypop3;

my ($pos) = restore_state();

$startsize = (stat $logfile)[7];

if (!defined $pos) {
  # Initial run.
  $pos = $startsize;
}

if ($startsize < $pos) {
  # Log rotated
  parseDovecotfile ($rotlogfile, $pos, (stat $rotlogfile)[7]);
  $pos = 0;
}

parseDovecotfile ($logfile, $pos, $startsize);
$pos = $startsize;

save_state($pos);

print "multigraph dovecot_connections\n";
print "connections.value $connections\n";
print "connectionsimap.value $connectionsimap\n";
print "connectionspop3.value $connectionspop3\n";
print "connectionsproxyimap.value $connectionsproxyimap\n";
print "connectionsproxypop3.value $connectionsproxypop3\n";
print "multigraph dovecot_connected\n";
print "connected.value $connected\n";
print "connectedimap.value $connectedimap\n";
print "connectedpop3.value $connectedpop3\n";
print "connectedproxyimap.value $connectedproxyimap\n";
print "connectedproxypop3.value $connectedproxypop3\n";
print "multigraph dovecot_logins\n";
print "login.value $login\n";
print "pop3login.value $pop3login\n";
print "imaplogin.value $imaplogin\n";
print "tls.value $tls\n";
print "starttls.value $starttls\n";
print "ssl.value $ssl\n";
print "aborted.value $aborted\n";


sub parseDovecotfile {
  my ($fname, $start, $stop) = @_;
  open (logf, $fname) or exit 3;
  seek (logf, $start, 0) or exit 2;

  while (tell (logf) < $stop) {
    my $line =<logf>;
    chomp ($line);

    if ($line =~ m/Aborted/) {
      $aborted++;

    } elsif ($line =~ m/Login:/) {
      $login++;

      if ($line =~ m/TLS/) {
        $tls++;
        if ($line =~ m/lport=143/ ||
            $line =~ m/lport=110/) {
            $starttls++;
        }
      } elsif ($line =~ m/SSL/) {
        $ssl++;
      }

      if (     $line =~ m/pop3-login:/) {
        $pop3login++;
      } elsif ($line =~ m/imap-login:/) {
        $imaplogin++;
      }
    }
  }
  close(logf);
}

# vim:syntax=perl
